﻿using System;
using System.Web;
using System.Web.Caching;

namespace InhollandAir.auxiliary
{
    public class CustomerFactory
    {
        public static Customer WithCookie(HttpCookie cookie)
        {
            if (cookie == null) return null;
            var username = cookie[Cookie.SessionName];
            var sessionKey = cookie[Cookie.SessionLoginKey];


            if (username == null || sessionKey == null || HttpContext.Current.Cache.Get(username) == null) return null;
            return HttpContext.Current.Cache.Get(username).ToString() == sessionKey ? WithUsername(username, sessionKey) : null;
        }

        public static Customer WithCredentials(string username, string password)
        {
            var customer = Sql.GetUserWithCredentials(username, password);
            if (customer == null) return null;

            var cookie = HttpContext.Current.Request.Cookies[Cookie.SessionKey] ?? new HttpCookie(Cookie.SessionKey);

            cookie[Cookie.SessionName] = username;
            cookie[Cookie.SessionLoginKey] = CryptoRandom.GetUniqueKey(Cookie.SessionLoginKeyLength);
            cookie.HttpOnly = true;
            cookie.Secure = true;

            cookie.Expires = DateTime.Now.AddDays(Cookie.SessionLength);

            HttpContext.Current.Response.Cookies.Add(cookie);
            HttpContext.Current.Cache.Add(username, cookie[Cookie.SessionLoginKey], null, DateTime.Now.AddMinutes(Customer.SessionExpireLength), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);

            Logging.LogEvent(customer.Id, HttpContext.Current.Request.Url, "Cache and cookie created at login", string.Empty, false);

            return customer;
        }

        private static Customer WithUsername(string username, string sessionKey)
        {
            var realSessionKey = HttpContext.Current.Cache.Get(username);
            if (sessionKey == (string) realSessionKey)
            {
                return Sql.GetUserWithUsername(username);
            }
            return null;
        }

        public delegate void TryLoginDelegate(Customer customer, bool success);
        public static void TryLogin(TryLoginDelegate tryLoginDelegate)
        {
            Logging.LogEvent(0, HttpContext.Current.Request.Url, "Login attempt from " + HttpContext.Current.Request.UserHostName, string.Empty, false);
            var customer = WithCookie(Cookie.UserSession());
            tryLoginDelegate(customer, customer != null);
        }

        public static void TryLogin(string username, string password, TryLoginDelegate tryLoginDelegate)
        {
            Logging.LogEvent(0, HttpContext.Current.Request.Url, "Login attempt from " + HttpContext.Current.Request.UserHostName, string.Empty, false);
            var customer = WithCredentials(username, password);
            tryLoginDelegate(customer, customer != null);
        }

        public static void Logout(bool reloadPage)
        {
            Logging.LogEvent(0, HttpContext.Current.Request.Url, "Logout from " + HttpContext.Current.Request.UserHostName, string.Empty, false);
            Cookie.ClearUserSession();
            if(reloadPage) HttpContext.Current.Response.Redirect(HttpContext.Current.Request.Url.ToString());
        }

        internal static bool Book(Customer _customer, Airplane _airplane, Airport _fromAirport, Airport _toAirport, DateTime _startDate)
        {
            Logging.LogEvent(0, HttpContext.Current.Request.Url, "Charter flight booked from " + HttpContext.Current.Request.UserHostName, string.Empty, false);
            return Sql.InsertCharterFlightWith(_customer, _airplane, _fromAirport, _toAirport, _startDate);
        }
    }
}